Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 <<   zurück
Visual Basic 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual Basic 2005

Visual Basic 2005
1.233 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-585-1
gp Kapitel 6 Vererbung, Polymorphie und Schnittstellen
  gp 6.1 Basisklassen und abgeleitete Klassen
    gp 6.1.1 Die Ableitung einer Klasse
    gp 6.1.2 Klassen, die nicht vererben können
    gp 6.1.3 Zusammenfassung
  gp 6.2 Konstruktoren in abgeleiteten Klassen
    gp 6.2.1 Allgemeines
    gp 6.2.2 Die Konstruktoren der Klasse »GraphicCircle«
    gp 6.2.3 Der Zugriffsmodifizierer »Protected«
    gp 6.2.4 Konstruktorverkettung
    gp 6.2.5 Finalizer-Verkettung
    gp 6.2.6 Zusammenfassung
    gp 6.2.7 Der Stand des Projekts »CircleApplication«
  gp 6.3 Die Methoden in einer abgeleiteten Klasse
    gp 6.3.1 Geerbte Methoden mit »Shadows« verdecken
    gp 6.3.2 Überladen einer Basisklassenmethode
  gp 6.4 Ereignisse in der Vererbung
  gp 6.5 »Hat-eine«-Beziehungen (Aggregation)
    gp 6.5.1 Weiterleitung einer internen Objektreferenz
    gp 6.5.2 Verbergen des internen Objekts
    gp 6.5.3 Innere Klassen
  gp 6.6 Typumwandlung von Objektvariablen
    gp 6.6.1 Die implizite Typumwandlung von Objektreferenzen
    gp 6.6.2 Die explizite Typumwandlung von Objektreferenzen
    gp 6.6.3 Zusammenfassung
  gp 6.7 Abstrakte Klassen und Methoden
    gp 6.7.1 Problembeschreibung
    gp 6.7.2 Abstrakte Definitionen
  gp 6.8 Polymorphie
    gp 6.8.1 Überschreibbare Methoden mit »Overridable«
    gp 6.8.2 Inhomogene Mengen
    gp 6.8.3 Verdecken und Überschreiben geerbter Methoden
    gp 6.8.4 Überschreiben der Methode »ToString()« der Klasse »Object«
    gp 6.8.5 Nicht überschreibbare Methoden
    gp 6.8.6 Die Referenzen »Me«, »MyBase« und »MyClass«
    gp 6.8.7 Zusammenfassung
  gp 6.9 Erweiterung der Klassenhierarchie »CircleApplication«
    gp 6.9.1 Die Klasse »GeometricObject«
  gp 6.10 Schnittstellen
    gp 6.10.1 Einführung in die Schnittstellen
    gp 6.10.2 Schnittstellendefinition
    gp 6.10.3 Schnittstellenimplementierung
    gp 6.10.4 Abstrakte Klassen vs. Schnittstellen
    gp 6.10.5 Zusammenfassung


Galileo Computing

6.2 Konstruktoren in abgeleiteten Klassen  downtop


Galileo Computing

6.2.1 Allgemeines  downtop

Bei der Erzeugung des Objekts einer Subklasse gelten dieselben Regeln wie beim Erzeugen des Objekts einer Basisklasse:

gp  Es wird generell ein Konstruktor aufgerufen.
gp  Die Subklassenkonstruktoren dürfen überladen werden.

Es gibt jedoch eine Besonderheit, die im Zusammenhang mit den Konstruktoren beachtet werden muss:


Konstruktoren werden grundsätzlich nicht von der Basisklasse an die Subklasse vererbt.


Daher müssen alle Konstruktoren, die in einer abgeleiteten Klasse benötigt werden, definiert werden. Das gilt auch für den statischen Initialisierer.


Galileo Computing

6.2.2 Die Konstruktoren der Klasse »GraphicCircle«  downtop

Abgesehen vom impliziten, parameterlosen Standardkonstruktor ist die Klasse GraphicCircle noch ohne Konstruktor. Um dem Anspruch zu genügen, einem Circle-Objekt auch hinsichtlich der Instanziierbarkeit gleichwertig zu sein, benötigen wir insgesamt vier Konstruktoren, die in der Lage sind, entweder den Radius oder den Radius samt der beiden Mittelpunktkoordinaten entgegenzunehmen. Außerdem müssen wir berücksichtigen, dass Objekte vom Typ GraphicCircle gleichzeitig Objekte vom Typ Circle sind. Die logische Konsequenz ist, den Objektzähler mit jedem neuen GraphicCircle-Objekt zu erhöhen.

Mit diesen Vorgaben, die identisch mit denen in der Basisklasse sind, sieht der erste und, wie Sie noch sehen werden, etwas blauäugige Entwurf der Erstellungsroutinen in der Klasse GraphicCircle zunächst folgendermaßen aus:


Public Class GraphicCircle
Inherits Circle
' ---------------- Konstruktoren ----------------
Public Sub New()
intCountCircles += 1
End Sub
Public Sub New(ByVal radius As Single)
Me.New()
Me.Radius = radius
End Sub
Public Sub New(ByVal radius As Single, _
ByVal x As Single, ByVal y As Single)
Me.New(radius)
Me.center.X = x
Me.center.Y = y
End Sub
Public Sub New(ByVal radius As Double, ByVal pt As Point)
Me.New(radius)
Me.center = pt
End Sub
End Class

Der Versuch, diesen Programmcode zu kompilieren, endet jedoch in einem Fiasko, denn die Felder center und countCircles kann der VB-Compiler nicht erkennen und verweigert deswegen den Zugriff. Der Grund hierfür ist recht einfach: Diese Felder sind in der Basisklasse Circle Private deklariert, und private Member sind grundsätzlich nur in der deklarierenden Klasse bekannt. Obwohl aus objektorientierter Sicht ein Objekt vom Typ GraphicCircle auch gleichzeitig als ein Objekt vom Typ Circle angesehen wird, kann die strikte Kapselung einer privaten Variablen durch die Vererbung nicht aufgebrochen werden. Nur der Code in der Klasse Circle hat Zugriff auf die privaten Klassenmitglieder.


Galileo Computing

6.2.3 Der Zugriffsmodifizierer »Protected«  downtop

Einen Ausweg aus diesem Dilemma, ein Klassenmitglied einerseits gegen den unbefugten Zugriff von außen zu schützen und andererseits einer abgeleiteten Klasse zu vererben, bietet ein Zugriffsmodifizierer, der im Zusammenhang mit der Implementierungsvererbung eine tragende Rolle hat: Protected.


Member, die Protected deklariert sind, verhalten sich ähnlich wie Private deklarierte: Sie verhindern den unzulässigen Zugriff von außerhalb, garantieren andererseits jedoch, dass aus einer abgeleiteten Klasse darauf zugegriffen werden kann.


Diese Erkenntnis führt zu einem Umdenken bei der Implementierung einer Klasse: Muss davon ausgegangen werden, dass die Klasse als Basisklasse ihre Dienste zur Verfügung stellt, sind alle privaten Member, die einer abgeleiteten Klasse zur Verfügung stehen sollen, Protected zu deklarieren. Daher müssen wir in der Klasse Circle noch folgende Änderungen vornehmen:


Protected center As Point
Protected dblRadius As Double
Protected Shared intCountCircles As Integer

Erst jetzt ist die Klasse Circle tatsächlich vererbungsfähig, und der VB-Compiler wird keinen Fehler mehr melden.


Galileo Computing

6.2.4 Konstruktorverkettung  downtop

Wir wollen nun die Implementierung in Main testen, indem wir ein Objekt des Typs GraphicCircle erzeugen und uns den Stand des Objektzählers, der aus der Circle-Klasse geerbt wird, an der Konsole ausgeben lassen. Der Code dazu lautet:


Sub Main()
Dim gc As GraphicCircle = New GraphicCircle()
Console.WriteLine("Anzahl der Kreise = {0}", _
GraphicCircle.CountCircles)
End Sub

Völlig unerwartet werden wir mit einer Situation konfrontiert, die wir nicht erwartet haben. Mit


Anzahl der Kreise = 2

wird uns suggeriert, wir hätten zwei Kreisobjekte erzeugt, obwohl wir doch tatsächlich nur einmal den New-Operator benutzt haben und sich folgerichtig tatsächlich auch nur ein konkretes Objekt im Speicher befinden kann.

Das Ergebnis ist falsch und beruht auf der bisher noch nicht berücksichtigten Aufrufverkettung zwischen den Sub- und den Basisklassenkonstruktoren. Konstruktoren werden nicht vererbt und müssen deshalb – falls erforderlich – in jeder abgeleiteten Klasse neu definiert werden. Dennoch kommt den Konstruktoren einer Basisklasse eine entscheidende Bedeutung zu.


Bei der Initialisierung des Objekts vom Typ einer abgeleiteten Klasse wird in jedem Fall zuerst ein Basisklassenkonstruktor aufgerufen. Es kommt zu einer Top-down-Verkettung der Konstruktoren, angefangen bei der obersten Basisklasse bis hinunter zu der Klasse, deren Konstruktor ausgeführt werden muss.


Die Verkettung der Konstruktoraufrufe dient dazu, zunächst die geerbten Komponenten der Basisklasse zu initialisieren. Erst danach wird der Konstruktor der Subklasse ausgeführt, der eigene Initialisierungen vornehmen kann und gegebenenfalls auch die Vorinitialisierung der geerbten Komponenten an die Bedürfnisse der abgeleiteten Klasse anpasst. Standardmäßig wird implizit immer zuerst der parameterlose Konstruktor der Basisklasse aufgerufen.

Wir wollen uns das an einem einfachen Beispiel verdeutlichen.


' --------------------------------------------------------------
' Beispiel: ...\Kapitel 6\KonstruktorVerkettung
' --------------------------------------------------------------
' ----- Basisklasse -----
Class BaseClass
' Standardkonstruktor
Public Sub New()
Console.WriteLine("Konstruktor in 'BaseClass'")
End Sub
End Class
' ----- SubClass1 leitet BaseClass ab -----
Class SubClass1
Inherits BaseClass
' Standardkonstruktor
Public Sub New()
Console.WriteLine("Konstruktor in 'SubClass1'")
End Sub
End Class
' ----- SubClass2 leitet SubClass1 ab -----
Class SubClass2
Inherits SubClass1
' Standardkonstruktor
Public Sub New()
Console.WriteLine("Konstruktor (parameterlos) in 'SubClass2'")
End Sub
' parameterbehafteter Konstruktor
Public Sub New(ByVal x As Integer)
Console.WriteLine("Konstruktor (parametrisiert) in 'SubClass2'")
End Sub
End Class

Die Klasse BaseClass dient als Basisklasse der Klasse SubClass1, die ihrerseits wiederum Basisklasse der Klasse SubClass2 ist. In allen Klassen ist der parameterlose Konstruktor implementiert, in SubClass2 zusätzlich noch ein parametrisierter. Um die Verkettung der Konstruktoren zu testen, werden zwei Objekte des Typs SubClass2 erzeugt: einmal durch Aufruf des parameterlosen Konstruktors, im zweiten Fall mit dem Aufruf des parametrisierten.


Module Module1
Sub Main()
Dim obj1 As SubClass2 = New SubClass2()
Console.WriteLine("---------------------------")
Dim obj2 As SubClass2 = New SubClass2(2)
Console.ReadLine()
End Sub
End Module

Die Ausgabe an der Konsole bestätigt die Aussage, dass implizit zuerst der parameterlose Basisklassenkonstruktor aufgerufen wird, danach der Konstruktor des eigentlichen Objekts.


Konstruktor in 'BaseClass'
Konstruktor in 'SubClass1'
Konstruktor (parameterlos) in 'SubClass2'
-----------------------------
Konstruktor in 'BaseClass'
Konstruktor in 'SubClass1'
Konstruktor (parametrisiert) in 'SubClass2'

Dabei ist es bedeutungslos, ob das Objekt einer abgeleiteten Klasse mit oder ohne Argumente instanziiert wird, denn der implizite Aufruf landet immer beim parameterlosen Konstruktor der Basisklasse. Wenn wir präzise sein wollen, müssen wir sogar sagen, dass die Aufrufverkettung nicht in BaseClass beginnt, sondern tatsächlich in Object, da diese Klasse oberste Basisklasse aller .NET-Klassen ist und als einzige Klasse selbst keine Basisklasse besitzt.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 6.3     Aufrufverkettung der Konstruktoren

Die Konstruktorverkettung hat maßgeblichen Einfluss auf die Modellierung einer Klasse, die parametrisierte Konstruktoren enthält. Eine konstruktorlose Klasse enthält grundsätzlich immer den impliziten parameterlosen Konstruktor. Ergänzt man aber eine Klassendefinition um einen parametrisierten, existiert der implizite parameterlose nicht mehr.

Wird das Objekt einer ableitenden Klasse erzeugt, kommt es – wie wir oben gesehen haben – zum Aufruf des parameterlosen Konstruktors der Basisklasse. Sie sollten sich dieses Effekts bewusst sein, wenn Sie eine ableitbare Klasse entwickeln und parametrisierte Konstruktoren hinzufügen. Im Bedarfsfall ist der parameterlose Konstruktor zu implementieren – selbst dann, wenn er keinen Programmcode enthält.

Die Konstruktorverkettung steuern

Nun kann auch das scheinbar unsinnige Ergebnis des Objektzählers des vorhergehenden Abschnitts erklärt werden, der bei der Instanziierung eines Objekts vom Typ GraphicCircle behauptete, zwei Kreisobjekte würden vorliegen, obwohl es doch nachweislich nur eins war. Durch die Konstruktorverkettung wird – so wie es die noch unveränderte Implementierung der Konstruktoren vorgibt – zunächst der parameterlose Konstruktor der Basisklasse Circle aufgerufen, danach der der Klasse GraphicCircle. In beiden wird der Objektzähler erhöht und führt letztendlich zu einem falschen Zählerstand.

Die Ursache des Problems ist die Duplizität der Konstruktorimplementierung in beiden Klassen. Codewiederholung wird in der Programmierung vermieden, indem der wiederholt aufzurufende Code in einer eigenen Prozedur ausgelagert wird, die immer dann aufgerufen wird, wenn sie benötigt wird. Sehr ähnlich kann das Problem auch bei den Konstruktoren gelöst werden: Aus der Subklasse heraus wird ein bestimmter Konstruktor der Basisklasse aufgerufen.

Um eine Methode der Basisklasse aufzurufen – und als eine solche werden natürlich auch die Konstruktoren angesehen –, bietet Visual Basic 2005 das Schlüsselwort MyBase an.

Ersetzen wir den parameterlosen Konstruktor der Subklasse GraphicCircle durch


' Konstruktor der Klasse GraphicCircle
Public Sub New()
MyBase.New()
End Sub

und schreiben danach eine kleine Testroutine, wird die Ausgabe des Objektzählers den korrekten Stand wiedergeben.

Konstruktoren können viele Anweisungen enthalten. Der Basisklassenkonstruktor wird grundsätzlich immer vor allen anderen Anweisungen als Erstes aufgerufen. Da spielt es keine Rolle, ob der Aufruf implizit erfolgt oder nicht. Mit anderen Worten: Wollen Sie per Code einen Basisklassenkonstruktor explizit aufrufen, muss diese Anweisung immer als erste in der Konstruktorimplementierung stehen.

Sehen wir uns nun abschließend die überarbeitete Fassung der GraphicCircle-Konstruktoren an:


Public Sub New()
MyBase.New()
End Sub
Public Sub New(ByVal radius As Single)
MyBase.New(radius)
End Sub
Public Sub New(ByVal radius As Single, ByVal x As Single, _
ByVal y As Single)
MyBase.New(radius, x, y)
End Sub
Public Sub New(ByVal radius As Double, ByVal pt As Point)
MyBase.New(radius, pt)
End Sub

Beim parameterlosen Konstruktor könnten wir auf MyBase verzichten, weil der Aufruf auch ohne diese Angabe an den parameterlosen Basisklassenkonstruktor weitergeleitet wird.

Schreiben wir jetzt eine Testroutine, z.  B.:


Dim gc As GraphicCircle = New GraphicCircle()
Console.WriteLine("Anzahl der Kreise = {0}", _
GraphicCircle.CountCircles)

wird die Ausgabe des Objektzählers tatsächlich den korrekten Stand wiedergeben.

Der Zugriff auf Entitäten der Basisklasse mit »MyBase«

Mit MyBase kann auf alle öffentlichen Mitglieder der direkten Basisklasse Bezug genommen werden. Dabei gilt, dass die Methode der Basisklasse durchaus eine Methode sein kann, welche die Basisklasse selbst geerbt hat, also aus Sicht der MyBase-implementierenden Subklasse aus einer indirekten Basisklasse stammt. Ein umgeleiteter Aufruf an eine indirekte Basisklasse mit


MyBase.MyBase.TestProc()

ist nicht gestattet. Ist die Methode parametrisiert, müssen die Argumente der Definition in der Parameterliste entsprechen.

Beim Einsatz von MyBase sind einige Dinge zu beachten:

gp  Mit MyBase kann nur auf die in der direkten Basisklasse öffentlich definierten sowie auf die geerbten Member zugegriffen werden. Der Zugriff erfolgt mit der allgemein üblichen Punktnotation und setzt die korrekte Angabe der Parameterliste voraus.
gp  MyBase ist eine implizite Referenz und kann daher auch nicht einer Variablen zugewiesen werden oder als Übergabeargument an eine Prozedur dienen.
gp  Da mein MyBase nur eine implizite Referenz ist und kein Objekt im eigentlichen Sinne, ist die Benutzung in einem Vergleich mit dem Schlüsselwort Is nicht zulässig.

Der parameterlose Konstruktor der Basisklasse wird immer dann automatisch aufgerufen, wenn in der ersten Anweisung des aufgerufenen Konstruktors der Subklasse mit MyBase.New([Parameterliste]) kein bestimmter Aufruf eines beliebigen Basisklassenkonstruktors erzwungen wird.

Diesem Umstand muss beim Design einer Klasse, die als Basisklasse abgeleitet werden kann, besondere Beachtung geschenkt werden. Enthält nämlich eine ableitbare Klasse parametrisierte Konstruktoren, ersetzen diese den impliziten, parameterlosen Standardkonstruktor. Er existiert schlichtweg nicht mehr – es sei denn, er ist ebenfalls explizit implementiert. Daher gilt die folgende, wichtige Regel:


Werden in einer ableitbaren Klasse parameterbehaftete Konstruktoren implementiert, sollte der parameterlose Konstruktor selbst dann explizit codiert werden, wenn er keinen Code enthält.


Halten Sie sich nicht an diese Regel, führt das zu einer Fehlermeldung in der abgeleiteten Klasse, wenn die Existenz des Standardkonstruktors vorausgesetzt wird.


Galileo Computing

6.2.5 Finalizer-Verkettung  downtop

Konstruktoren dienen der Initialisierung eines Objekts, die Finalize-Methode wird aufgerufen, wenn der Garbage Collector auf ein Objekt stößt, das im Programmcode nicht weiter benutzt wird.

Der verkettete Konstruktoraufruf in einer Klassenhierarchie findet in ähnlicher Weise auch statt, wenn der Garbage Collector bei seinen Aufräumarbeiten auf die Finalize-Methode in einer Subklasse stößt. Der Ablauf der Verkettung spielt sich allerdings in umgekehrter Reihenfolge ab: Zuerst werden die Aufräumarbeiten in der Subklasse geleistet, danach die in der direkten Basisklasse. Diese Bottom-up-Verkettung unterliegt allerdings keinem automatischen Mechanismus, sondern muss explizit gesteuert werden.


Protected Overrides Sub Finalize()
'Anweisungen
MyBase.Finalize
End Sub

Erst die letzte Anweisung in der Finalize-Methode sollte den Aufruf der gleichnamigen Methode in der Basisklasse bewirken. In der folgenden Abbildung 6.4 ist die Aufrufverkettung anschaulich nachzuvollziehen.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 6.4     Die Aufrufverkettung von Finalisierungsmethoden

Der Gültigkeitsbereich von Finalize ist Protected, d. h., sie kann nur aus der eigenen Klasse heraus oder aus einer abgeleiteten Klasse heraus aufgerufen werden. Definiert ist Finalize in der Klasse Object in der Weise, dass die Methode überschrieben werden darf. Wie Sie später noch sehen werden, muss eine Methode, die eine andere gleichnamige Methode in der Basisklasse überschreibt, mit Overrides gekennzeichnet werden.


Galileo Computing

6.2.6 Zusammenfassung  downtop

gp  Konstruktoren werden grundsätzlich nicht von der Basisklasse an die Subklasse vererbt.
gp  Private deklarierte Mitglieder in einer Basisklasse sind in der abgeleiteten Klasse nicht sichtbar. Um das Prinzip der Kapselung nicht aufzubrechen und diese Klassenmitglieder zu vererben, muss das entsprechende Mitglied in der Basisklasse Protected deklariert werden.
gp  Sub- und Basisklassenkonstruktor hängen in der Weise voneinander ab, dass zuerst der Basisklassenkonstruktor und danach der Konstruktor der abgeleiteten Klasse ausgeführt wird.
gp  Wenn nicht anders angegeben, wird in einer abgeleiteten Klasse implizit zuerst der parameterlose Standardkonstruktor der Basisklasse aufgerufen, bevor die erste Anweisung im Subklassenkonstruktor ausgeführt wird.
gp  Mit dem Schlüsselwort MyBase kann die implizite Konstruktorverkettung zwischen zwei in einer Vererbungsbeziehung stehenden Klassen durch eine benutzerdefinierte ersetzt werden.
gp  Stößt der Garbage Collector bei seinen Aufräumarbeiten im freizugebenden Objekt auf einen Destruktor, werden alle Destruktoren in der Vererbungslinie durchlaufen, beginnend mit dem des aktuellen Objekts.
gp  Der Aufruf des Basisklassendestruktors erfolgt erst, nachdem alle Anweisungen des Destruktors der Subklasse ausgeführt worden sind.

Galileo Computing

6.2.7 Der Stand des Projekts »CircleApplication«  toptop

Fassen wir an dieser Stelle noch einmal alle Ergänzungen und Änderungen des Projekts CircleApplication zusammen.


' ----------------------------------------------------------
' Beispiel: ...\Kapitel 6\CircleApplication_4
' ----------------------------------------------------------
Public Class Circle
Implements IDisposable
' ---------- Instanzfelder --------------
Private bolReduced As Boolean
Protected center As Point
Protected dblRadius As Double
' --------- statische Felder --------------
Protected Shared intCountCircles As Integer
...
End Class
Public Class GraphicCircle
Inherits Circle
' Konstruktoren
Public Sub New()
End Sub
Public Sub New(ByVal radius As Double)
MyBase.New(radius)
End Sub
Public Sub New(ByVal radius As Double, _
ByVal x As Integer, ByVal y As Integer)
MyBase.New(radius, x, y)
End Sub
Public Sub New(ByVal radius As Double, ByVal pt As Point)
MyBase.New(radius, pt)
End Sub
' Typspezifische Methode
Public Sub Draw()
Console.WriteLine("Der Kreis wird gezeichnet")
End Sub
End Class

 <<   zurück
  
  Zum Katalog
Zum Katalog: Visual Basic 2005
Visual Basic 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Visual C# 2005






 Visual C# 2005


Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Das Programmierhandbuch SQL Server 2005






 Das Programmier-
 handbuch
 SQL Server 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de